import __builtin__
from direct.gui.DirectGui import *
from client.gamestates.staterunningsession import Role
import sys
from pandac.PandaModules import TextNode
from direct.gui.OnscreenText import OnscreenText

class GuiManager():
    ###############################################################################################################
    ###############################################################################################################
    ########################                         C O M M O N                           ########################
    ###############################################################################################################
    ###############################################################################################################

    def __init__(self):
        print("INIT GUIMANAGER")
        self.curGUI = {}
        self.selGUI = {}

        # some size and position calculations which occure
        # if the application window is resized
        self.ratioX = 1.0
        self.ratioY = 1.0


    def destroy_current_gui(self):
        for ele in self.curGUI.viewvalues():
            ele.destroy()

        self.curGUI = {}
        self.destroy_selection()

    def update(self, dt):
        if "Money" in self.curGUI:
            self.curGUI["Money"]["text"] = "$ " + str(__builtin__.base.gamestatemanager.getState("RunningSession").curMoney)
            #self.curGUI["Money"].resetFrameSize()

    def toggle_element_active(self, eleName, text, active):
        if __builtin__.base.guimanager.curGUI.has_key(eleName):
            element = __builtin__.base.guimanager.curGUI[eleName]

            element["text"] = text
            element.resetFrameSize()

            col = __builtin__.base.guimanager.curGUI["BtnMulti"]["frameColor"]

            if active:
                element["state"] = DGG.NORMAL
                element["frameColor"] = (col[0], col[1], col[2], 1)
            else:
                element["state"] = DGG.DISABLED
                element["frameColor"] = (col[0], col[1], col[2], 0.25)

    def changeNickname(self, nick):
        __builtin__.base.networkmanager.my_user.name = nick
        __builtin__.base.networkmanager.send_changed_nick()




    ###############################################################################################################
    ###############################################################################################################
    ########################                     M A I N    M E N U                        ########################
    ###############################################################################################################
    ###############################################################################################################

    def create_mainmenu(self):
        self.curGUI.update({"Background": DirectFrame(frameTexture="client/textures/gui/BG.jpg", frameSize = (-1,1,-1,1), scale=1)})#, pos=(-1.35,0,-1))})
        self.curGUI["Background"].reparentTo(__builtin__.base.render2d)
        self.curGUI.update({"BtnMulti": DirectButton(text="Login", pos=(0, 0, -0.2), scale=0.1, command=self.login_pressed)})
        self.curGUI.update({"PlayerName": DirectEntry(initialText="Enter your Name.", cursorKeys = True, pos = (-0.4, 0, 0), width=8, scale = 0.1, focusInCommand = self.clear_name_input)})
        self.curGUI.update({"BtnExit": DirectButton(text="Exit Game", pos=(-1, 0, -0.9), scale=0.1, command=sys.exit)})
        #self.curGUI.update({"LabelMain": OnscreenText(text = 'OMPTD', pos = (0, 0.6), scale = 0.15)})

    def login_pressed(self):
        if self.curGUI["PlayerName"].get() != "" and self.curGUI["PlayerName"].get() != "Enter your Name.":
            __builtin__.base.networkmanager.my_user.name = self.curGUI["PlayerName"].get()
            __builtin__.base.networkmanager.init_network()
        else:
            self.clear_name_input()

    def clear_name_input(self):
        self.curGUI["PlayerName"].enterText("")



    ###############################################################################################################
    ###############################################################################################################
    ########################                        L O B B Y                              ########################
    ###############################################################################################################
    ###############################################################################################################

    def create_lobby(self):
        self.curGUI.update({"Background": DirectFrame(frameTexture="client/textures/gui/BG.jpg", frameSize = (-1,1,-1,1), scale=1)})#, pos=(-1.35,0,-1))})
        self.curGUI["Background"].reparentTo(__builtin__.base.render2d)
        self.curGUI.update({"BtnCreate": DirectButton(text="Create Lobby", pos=(0.9, 0, -0.9), scale=0.1, command=__builtin__.base.networkmanager.send_create_session)})
        #self.curGUI.update({"BtnJoin": DirectButton(text="Join Game", pos=(0.2, 0, -0.9), scale=0.1)})
        self.curGUI.update({"BtnBack": DirectButton(text="Back", pos=(-1, 0, -0.9), scale=0.1, command=__builtin__.base.gamestatemanager.demand, extraArgs=["MainMenu"])})
        self.curGUI.update({"LabelMain": DirectLabel(text="MultiLobby", pos=(-1, 0, 0.9), scale=0.1)})
        self.curGUI.update({"LabelPlayerOnline": DirectLabel(text="0 Online", pos=(1, 0, 0.9), scale=0.1)})

        self.create_lobby_list()
        self.create_lobby_chat()

    def create_lobby_list(self):
        myScrolledList = DirectScrolledList(
            decButton_pos= (0, 0, -0.46),
            decButton_text = "SCROLL DOWN",
            decButton_text_scale = 0.05,
            decButton_borderWidth = (0.005, 0.005),

            incButton_pos= (0, 0, 0.44),
            incButton_text = "SCROLL UP",
            incButton_text_scale = 0.05,
            incButton_borderWidth = (0.005, 0.005),

            frameSize = (-0.5, 0.5, -0.5, 0.5),
            frameColor = (0.2,0.2,0.2,0.5),
            pos = (0.6, 0, 0),
            scale = 1,
            numItemsVisible = 4,
            forceHeight = 0.11,
            itemFrame_frameSize = (-0.45, 0.45, -0.4, 0.4),
            itemFrame_pos = (0, 0, 0),
        )
        self.curGUI.update({"SessionList": myScrolledList})

    def create_lobby_chat(self):
        # this frame will contain all our GUI elements
        frameMain = DirectFrame(
            # size of the frame
            frameSize = (-0.5*self.ratioX, 0.5*self.ratioX,
                         -0.5*self.ratioY, 0.5*self.ratioY),
            # position of the frame
            pos = (-0.6, 0, 0),
            # temporarly bg color
            frameColor = (0.2,0.2,0.2,0.5))
        # now we set up the GUI for sending and displaing messages
        # the Button which we use to send the Message to the other users
        btn_send = DirectButton(
            text = "Send",
            pos = (0.27*self.ratioX,0,-0.4*self.ratioY),
            scale = 0.1)

        # the Textbox where we write our Messages, which we
        # want to send over to the other users
        txt_msg = DirectEntry(
            initialText = "Enter Message here.",
            cursorKeys=True,
            pos=(-0.45*self.ratioX, 0, -0.45*self.ratioY),
            scale = 0.05,
            width = 10)

        # the Textbox which stores all the messages we send
        # or recieved over the Network
        txt_messages = DirectEntry(
            cursorKeys=False,
            pos=(-0.45*self.ratioX, 0, 0.4*self.ratioY),
            scale = 0.05,
            width = 18,
            numLines = 14)

        pl_name = DirectEntry(initialText = "playerName", cursorKeys = True, pos = (-0.45*self.ratioX,0,-0.35*self.ratioY), scale = 0.05, width = 10)

        # reparent all elements to the main frame
        btn_send.reparentTo(frameMain)
        txt_msg.reparentTo(frameMain)
        pl_name.reparentTo(frameMain)
        txt_messages.reparentTo(frameMain)

        self.curGUI.update({"txt_messages": txt_messages})
        self.curGUI.update({"txt_msg": txt_msg})
        self.curGUI.update({"PlayerName": pl_name})
        self.curGUI.update({"btn_send": btn_send})
        self.curGUI.update({"Chat": frameMain})

        txt_msg["command"] = self.send_chat_msg
        txt_msg["focusInCommand"] = self.clear_msg_input
        btn_send["command"] = self.send_chat_msg
        # set the extraArgs to None, so the text from
        # the textfield will be used as message
        # if the button is used for sending
        btn_send["extraArgs"] = [None]

        self.curGUI["PlayerName"]["command"] = self.changeNickname
        self.curGUI["PlayerName"].enterText(__builtin__.base.networkmanager.my_user.name)

    def send_chat_msg(self, shizeParameter):
        __builtin__.base.networkmanager.send_chat_msg(self.curGUI["txt_msg"].get())
        self.curGUI["txt_msg"].enterText("Enter Message here.")

    def set_chat_text(self, message_text):
        # get all messages from the textbox
        if "txt_messages" in self.curGUI:
            parts = self.curGUI["txt_messages"].get().split("\n")
            if len(parts) >= 10:
                cutParts = ""
                # as the textbox can only hold 10 lines cut out the first entry
                for i in range(1,len(parts)):
                    cutParts += parts[i] + "\n"
                self.curGUI["txt_messages"].enterText(cutParts + message_text)
            else:
                self.curGUI["txt_messages"].enterText(self.curGUI["txt_messages"].get() + "\n" + message_text)

    def update_user_online(self):
        if "LabelPlayerOnline" in self.curGUI:
            self.curGUI["LabelPlayerOnline"]["text"] = str(__builtin__.base.networkmanager.clients_online) + " Online"

    def clear_session_list(self):
        if str(__builtin__.base.gamestatemanager.curState.name) == "MultiLobby":
            self.curGUI["SessionList"].destroy()
            self.create_lobby_list()

    def clear_msg_input(self):
        self.curGUI["txt_msg"].enterText("")



    ###############################################################################################################
    ###############################################################################################################
    ########################                   C R E A T E   G A M E                       ########################
    ###############################################################################################################
    ###############################################################################################################

    def create_creategame(self):
        self.curGUI.update({"Background": DirectFrame(frameTexture="client/textures/gui/BG.jpg", frameSize = (-1,1,-1,1), scale=1)})#, pos=(-1.35,0,-1))})
        self.curGUI["Background"].reparentTo(__builtin__.base.render2d)

        self.curGUI.update({"Frame": DirectFrame(
            # size of the frame
            frameSize = (-0.7*self.ratioX, 0.7*self.ratioX,
                         -0.3*self.ratioY, 0.3*self.ratioY),
            # position of the frame
            pos = (0, 0, 0),
            # temporarly bg color
            frameColor = (0.2,0.2,0.2,0.5)
        )})

        self.curGUI.update({"LabelAtk": OnscreenText(
            text="Attacker: OPEN",
            pos=(-0.5, 0.07),
            scale=0.1,
            fg=(1,1,1,1),
            align=TextNode.ALeft
        )})
        self.curGUI.update({"LabelDef": OnscreenText(
            text="Defender: OPEN",
            pos=(-0.5, -0.13),
            scale=0.1,
            fg=(1,1,1,1),
            align=TextNode.ALeft
        )})

        self.curGUI["LabelAtk"].reparentTo(self.curGUI["Frame"])
        self.curGUI["LabelDef"].reparentTo(self.curGUI["Frame"])

        self.curGUI.update({"BtnBack": DirectButton(text="Back", pos=(-1, 0, -0.9), scale=0.1, command=self.leave_session)})
        self.curGUI.update({"BtnToggleRole": DirectButton(text="Switch Roles", pos=(0.4, 0, -0.4), scale=0.1, command=self.toggle_roles)})
        self.curGUI.update({"BtnStart": DirectButton(text="Start Game", pos=(0.9, 0, -0.9), scale=0.1, command=__builtin__.base.networkmanager.send_session_start)})

    def update_creategame(self):
        if str(__builtin__.base.gamestatemanager.curState.name) == "CreateGame":
            atk = __builtin__.base.gamestatemanager.getState("CreateGame").attacker
            defnd = __builtin__.base.gamestatemanager.getState("CreateGame").defender

            if atk != 0:
                self.curGUI["LabelAtk"]["text"] = "Attacker: " + str(atk.name)
            else:
                self.curGUI["LabelAtk"]["text"] = "Attacker: OPEN"

            if defnd != 0:
                self.curGUI["LabelDef"]["text"] = "Defender: " + str(defnd.name)
            else:
                self.curGUI["LabelDef"]["text"] = "Defender: OPEN"

            if __builtin__.base.gamestatemanager.getState("CreateGame").is_creator is True and atk != 0 and defnd != 0:
                self.curGUI["BtnStart"].show()
            else:
                self.curGUI["BtnStart"].hide()

    def toggle_roles(self):
        __builtin__.base.networkmanager.send_toggle_roles()

    def leave_session(self):
        __builtin__.base.networkmanager.send_session_left()


    ###############################################################################################################
    ###############################################################################################################
    ########################               R U N N I N G   S E S S I O N                   ########################
    ###############################################################################################################
    ###############################################################################################################

    def create_runningsession(self, role):
        # MONEY
        self.curGUI.update({"MoneyFrame": DirectFrame(
            frameTexture="client/textures/gui/gui_money.png",
            frameSize=(0, 3.42, 0, 1.15),
            pos=(-1.3, 0, 0.85),
            scale=0.15
        )})
        self.curGUI["MoneyFrame"].setTransparency(1)

        self.curGUI.update({"Money": OnscreenText(
            text=str(__builtin__.base.gamestatemanager.getState("RunningSession").curMoney),
            pos=(-1.25, 0.9),
            scale=0.1,
            fg=(1,1,1,1),
            align=TextNode.ALeft
        )})

        # BUILDING
        self.curGUI.update({"Info": DirectFrame(
            frameTexture="client/textures/gui/gui_buy.png",
            frameSize=(0, 8.78, 0, 2.35),
            scale=0.15,
            pos=(-0.02, 0, 0.7)
        )})
        self.curGUI["Info"].setTransparency(1)
        game = __builtin__.base.gamestatemanager.getState("RunningSession")

        if role == Role.ATTACKER:
            self.curGUI.update({"Knockknockbot": DirectButton(image="client/textures/anklopfer.png", pos=(1.1, 0, 0.85), scale=0.1, command=game.prepare_build, extraArgs=["Knockknockbot"])})
            self.curGUI.update({"Warpzone": DirectButton(image="client/textures/LandZone.png", pos=(0.8, 0, 0.85), scale=0.1, command=game.prepare_warpzone)})

        if role == Role.DEFENDER:
            self.curGUI.update({"Watertower": DirectButton(image="client/textures/TestTower.png", pos=(1.1, 0, 0.85), scale=0.1, command=game.prepare_build, extraArgs=["TestTower"])})

        #MENU OVERLAY
        self.curGUI.update({"overlay": DirectFrame(frameColor=(0, 0, 0, 0.75), frameSize=(-2, 2, -2, 2), pos=(0, 0, 0))})
        self.curGUI.update({"BtnBackGame": DirectButton(text="Back to Game", pos=(0, 0, 0.1), scale=0.1, command=self.hide_overlay)})
        self.curGUI.update({"BtnBackMenu": DirectButton(text="Back to Menu", pos=(0, 0, -0.1), scale=0.1, command=self.quit_session)})
        self.hide_overlay()

    def toggle_gui(self):
        if self.curGUI["Info"].isHidden():
            self.show_gui()
        else:
            self.hide_gui()

    def show_gui(self):
        self.curGUI["Info"].show()

        if __builtin__.base.gamestatemanager.getState("RunningSession").role == Role.ATTACKER:
            self.curGUI["Knockknockbot"].show()
            self.curGUI["Warpzone"].show()
        else:
            self.curGUI["Watertower"].show()

    def hide_gui(self):
        self.curGUI["Info"].hide()
        self.destroy_selection()

        if __builtin__.base.gamestatemanager.getState("RunningSession").role == Role.ATTACKER:
            self.curGUI["Knockknockbot"].hide()
            self.curGUI["Warpzone"].hide()
        else:
            self.curGUI["Watertower"].hide()

    def toggle_overlay(self):
        if self.curGUI["BtnBackGame"].isHidden():
            self.show_overlay()
        else:
            self.hide_overlay()

    def hide_overlay(self):
        self.curGUI["overlay"].hide()
        self.curGUI["BtnBackGame"].hide()
        #self.curGUI["BtnPauseGame"].hide()
        self.curGUI["BtnBackMenu"].hide()

    def show_overlay(self):
        self.curGUI["overlay"].show()
        self.curGUI["BtnBackGame"].show()
        #self.curGUI["BtnPauseGame"].show()
        self.curGUI["BtnBackMenu"].show()

    def quit_session(self):
        __builtin__.base.networkmanager.send_session_left()

    def create_tower_selection(self, tower):
        self.destroy_selection()
        self.selGUI.update({"Selection": DirectFrame(
            frameTexture="client/textures/gui/gui_select.png",
            frameSize=(0, 10.27, 0, 2.72),
            scale=0.15,
            pos=(-0.27, 0, -1)
        )})
        self.selGUI["Selection"].setTransparency(1)


        self.selGUI.update({"SelectionPicture": DirectFrame(frameTexture="client/textures/"+tower.name+".png", frameSize=(0, 0.22, 0, 0.22), pos=(0.25, 0, -0.95))})
        self.selGUI.update({"SelectionStats": OnscreenText(
            text=str(tower.name) + "\nDamage: " + str(tower.damage) +"\nAttackspeed: " + str(tower.attackspeed) + "\nRange: " + str(tower.range),
            pos=(0.2, -0.78),
            scale=0.05,
            fg=(1,1,1,1),
            align=TextNode.ARight
        )})
        game = __builtin__.base.gamestatemanager.getState("RunningSession")
        for x in range(0, len(tower.upgrades)):
            self.selGUI.update({"Upgrade"+str(x): DirectButton(image="client/textures/"+tower.upgrades[x]+".png", pos=(0.76+0.3*x, 0, -0.85), scale=0.1, command=game.request_upgrade, extraArgs=[tower, x])})

    def create_unit_selection(self, unit):
        self.destroy_selection()
        self.selGUI.update({"Selection": DirectFrame(
            frameTexture="client/textures/gui/gui_select.png",
            frameSize=(0, 10.27, 0, 2.72),
            scale=0.15,
            pos=(-0.27, 0, -1)
        )})
        self.selGUI["Selection"].setTransparency(1)
        self.selGUI.update({"SelectionPicture": DirectFrame(frameTexture="client/textures/"+unit.name+".png", frameSize=(0, 0.22, 0, 0.22), pos=(0.25, 0, -0.95))})
        self.selGUI.update({"SelectionStats": OnscreenText(
            text=str(unit.name) + "\nHealth: " + str(unit.hp) +"\nSpeed: " + str(unit.speed),
            pos=(0.2, -0.78),
            scale=0.05,
            fg=(1,1,1,1),
            align=TextNode.ARight
        )})
        game = __builtin__.base.gamestatemanager.getState("RunningSession")
        for x in range(0, len(unit.upgrades)):
            self.selGUI.update({"Upgrade"+str(x): DirectButton(image="client/textures/"+unit.upgrades[x]+".png", pos=(0.76+0.3*x, 0, -0.85), scale=0.1, command=game.request_upgrade, extraArgs=[unit, x])})

    def destroy_selection(self):
        for ele in self.selGUI.viewvalues():
            ele.destroy()
        self.selGUI = {}
        return